/* Copyright (c) 2022 渝州大数据实验室
 *
 * Lanius is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 *     http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.yzbdl.lanius.orchestrate.common.chain;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.yzbdl.lanius.orchestrate.common.exception.runtime.BusinessException;
import org.yzbdl.lanius.orchestrate.common.utils.SpringUtil;

import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;

/**
 * 删除检测链
 * 包含检测，成功后一并删除
 * @author chenjunhao@yzbdl.ac.cn
 * @date 2022-04-15 15:44
 */
public class DeleteCheckChain {

	public List<DeleteChain> deleteChains = new ArrayList<>();
	private int ind = 0;
	DataSourceTransactionManager dataSourceTransactionManager = SpringUtil.getBean(DataSourceTransactionManager.class);
	TransactionDefinition transactionDefinition = SpringUtil.getBean(TransactionDefinition.class);

	/**
	 * 不需要条件判断，直接执行
	 * @param func 执行函数
	 * @return 链对象
	 */
	public DeleteCheckChain addChain(Callable<Object> func){
		deleteChains.add(DeleteChain.builder()
				.explore(new DeleteExploreDto(true,""))
				.func(func)
				.build());
		return this;
	}

	/**
	 * 不需要执行，只需要判断
	 * @param condition 条件判断
	 * @param reason 理由
	 * @return 链对象
	 */
	public DeleteCheckChain addChain(boolean condition, String reason){
		deleteChains.add(DeleteChain.builder()
				.explore(new DeleteExploreDto(condition,reason))
				.func(null)
				.build());
		return this;
	}

	/**
	 * 同时需要条件判断和执行函数
	 * @param condition 条件
	 * @param func 执行函数
	 * @param reason 错误理由
	 * @return 链对象
	 */
	public DeleteCheckChain addChain(boolean condition, Callable<Object> func, String reason){
		deleteChains.add(DeleteChain.builder()
				.explore(new DeleteExploreDto(condition,reason))
				.func(func)
				.build());
		return this;
	}

//	//暂不用
//	public DeleteCheckChain addChain(DeleteChain deleteChain){
//		deleteChains.add(deleteChain);
//		return this;
//	}

	/**
	 * 执行当前链节点探索对象
	 * @return
	 */
	public DeleteExploreDto process(){
		if(ind == deleteChains.size()){
			this.execute();
			return DeleteExploreDto.builder().ok(true).build();
		}
		DeleteChain deleteChain = deleteChains.get(ind);
		DeleteExploreDto result = deleteChain.getExplore();
		if(result.isOk()){
			ind++;
			return process();
		}
		return DeleteExploreDto.builder()
				.ok(false)
				.reason(result.getReason())
				.build();
	}

	/**
	 * 执行删除
	 */
	public void execute() {
		TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
		try{
			for(DeleteChain deleteChain : deleteChains){
				if(deleteChain.getFunc()!=null){
					deleteChain.getFunc().call();
				}
			}
			dataSourceTransactionManager.commit(transactionStatus);
		}catch (Exception e){
			dataSourceTransactionManager.rollback(transactionStatus);
			throw new BusinessException("删除失败！");
		}
	}

}
